/*
 * Copyright 1992-4   BG Systems, Inc.
 * read_write.c
 *
 * routines that are to be called to read, & write to the LV824
 *
 * Author         Date       Comments
 * John Green     21-Oct-94  Major revision for v 3.0 EPROM
 * John Green     15-Jan-95  Updated for LV824.
 * John Green     01-Feb-95  Final touches for release 3.0
 * John Green     18-Feb-97  Clean up error handling
 * John Green     03-Mar-97  Add r_cs for copyright string
 * John Green     30-Oct-97  Modify for extended copyright string
 * John Green     29-Dec-97  Add check for encoders
 */


#include <stdio.h>
#include <string.h>

#ifdef ON_SGI
#include <unistd.h>
#else
#include <windows.h>
#endif

#include <errno.h>

#include "lv3.h"

static char SccsId[] = "@(#)read_write.c	1.11  28 Dec 1997";
extern RS_ERR rs_err;

#define MAX_TRIES 1000


void check_4_encoders(bglv *);
extern int w_pc(int, char *);
extern int r_pc(int, char *);
extern int w_lv(int, char *);
extern int pack_data(bglv *, char *);
extern int convert_serial(bglv *, char *);

/*    11-Feb-97   No longer needed
extern int sginap(long );
*/

int send_outputs(bglv *bgp)
{
   int st;
   char buf[64];
   long count;

/*
 *  Pack the numbers into a character string
 */
   st = pack_data(bgp, buf);
  
   count = strlen(buf);
/*
 *  Simply write the characters to the output serial port (ofd)
 */
#ifdef ON_MAC
   st = write_mac_sp( buf );
#endif
#ifdef ON_SGI
   st = write(bgp->sp_fd, buf, strlen(buf));
#else
   st = w_pc(bgp->sp_fd, buf);
#endif
   if (st != count)
   {
      printf("error: write()\nOSErr: %d\tcount:  %ld\n",st, count);
   }
   return(st);
}

int check_inputs(bglv *bgp)
{
   int st;
   int i;
   char str[64];
 
   rs_err.cycles++;
   if( rs_err.cycles % 1000 == 0 )
   {
      rs_err.cycles = 0;
      rs_err.thou++;
   }
 
/* 
 *  Read the serial port
 */
#ifdef ON_MAC
   st = read_mac_sp(bgp->str_len, &str[0]);
#endif
#ifdef ON_SGI
   st = read(bgp->sp_fd,str,bgp->str_len);
#else
   st = r_pc(bgp->sp_fd, str);
#endif
/*
 *  Read error
 */
   if (st < 0)
   {
      rs_err.rd++;
      printf("Major read error\n");
      return(-1);
   }

   i = 0;
/*
 *  We expect to get str_len characters -- if not, we will re-read 
 *  the port 100 times.
 *  If you repeatedly get messages when you are running this code
 *  to the effect that the characters were read after 25 re-tries,
 *  then you are trying to sample too fast.  If you repeatedly get
 *  100 re-tries, then you are probably have no communication at all.
 *  Check the chapter on "trouble shooting".
 */
   while ( st != bgp->str_len && i < 100)
   {
/*
 *  Check for LV824 requesting a handshake -- communication may have been 
 *  interupted, so we need to send an 'h' back.
 */
      if ( str[0] == 'h' )
      {
         printf("Handshake requested (%d)\n", i);
         w_lv(bgp->sp_fd, "h");
#ifdef ON_SGI         
         sginap(10);
#endif
         return(-1);
      }
/**
      sginap(1);
**/
#ifdef ON_MAC
   st = read_mac_sp(bgp->str_len, &str[0]);
#endif
#ifdef ON_SGI
      st = read(bgp->sp_fd,str,bgp->str_len);
#else
   st = r_pc(bgp->sp_fd, str);
#endif
      i++;
   }
#ifdef DEBUG
   if ( i > 0 )
      printf(" %d read attempts.\n", i);
#endif
 
   if (str[0] != 'p' || str[bgp->str_len - 1] != '\n')
   {
      printf("Unexpected string :  %s\n", str);
      rs_err.rd++;
      return(-1);
   }
   if (str[0] == '\n' )
      return (1);
 
/*
 *  Aha.  We got some real data !  So convert it from characters
 *  to meaningful numbers, and put them in the bgp data structure.
 */
   st = convert_serial(bgp, str);
 
   return st;
}

int r_lv(bglv *bgp)
{
   int st;
   int i = 0;
   char str[64];

   str[0] = '\0'; 
   rs_err.cycles++;
   if( rs_err.cycles % 1000 == 0 )
   {
      rs_err.cycles = 0;
      rs_err.thou++;
   }
 
#ifdef ON_MAC
   st = read_mac_sp(bgp->str_len, &str[0]);
#endif
#ifdef ON_SGI
   st = read(bgp->sp_fd,str,bgp->str_len);
#else
   st = r_pc(bgp->sp_fd, str);
#endif
   if (st < 0)
   {
      rs_err.rd++;
      perror("r_lv() ");
      return(-1);
   }
   while ( st != bgp->str_len && i < MAX_TRIES)
   {
/*
      sginap(1);
*/
#ifdef ON_MAC
   st = read_mac_sp(bgp->str_len, &str[0]);
#endif
#ifdef ON_SGI
      st = read(bgp->sp_fd,str,bgp->str_len);
#else
   st = r_pc(bgp->sp_fd, str);
#endif
      i++;
   }

   if ( i >= 200 )
      printf("%d read attempts. You are sampling too fast \n", i);
   if ( i >= MAX_TRIES )
      printf("%d read attempts. Dropped Frame \n", i);
 
   if ( st == 0)
   {
      printf("No chars in input buffer\n");
      rs_err.rd++;
      return(-2);
   }
   else if (str[0] != 'B' || str[bgp->str_len - 1] != '\n')
   {
      printf("%d:  %s\n", st, str);
      rs_err.rd++;
      return(-1);
   }

   st = convert_serial(bgp, str);
 
   return st;
}

int w_lv(int sp_fd, char *mode)
{
   int st;
#ifdef ON_MAC
   st = write_mac_sp( mode );
#endif
#ifdef ON_SGI
   st = write(sp_fd, mode, strlen(mode));
#else
   st = w_pc(sp_fd, mode);
#endif
   if (st < 0)
      rs_err.wrt++;
   return(st);
}

int get_ack(int sp_fd)
{
   int st;
   int i = 0;
   int chars = 100;
   char str[36];
 
#ifdef ON_MAC
   st = read_mac_sp(2, &str[0]);
#endif
#ifdef ON_SGI
   st = read(sp_fd,str,chars);
#else
   Sleep(500);
   st = r_pc(sp_fd, str);
#endif
   if (st < 0)
   {
      printf("get_ack():  read error\n");
      return(-1);
   }
   while ( st != 2 && i < 200)
   {
      if (st != 0 )
         printf("read: %s\n", str); 
#ifdef ON_SGI
      sginap(5);
#endif
#ifdef ON_MAC
   st = read_mac_sp(2, &str[0]);
#endif
#ifdef ON_SGI
      st = read(sp_fd,str,chars);
#else
   st = r_pc(sp_fd, str);
#endif
      i++;
   }
   if ( i > 2 )
      printf("Took %d tries \n", i);
   if ( i >= 200 )
      printf("Timeout %d chars in buffer \n", st);
 
   if (str[0] == 'a' )
   { 
#ifdef _DEBUG  // DN: I don't want to see this output in release mode
	   printf("Flybox: Setup OK\n"); 
#endif
       return (0);
   }
   else if (str[0] == 'f' )
   { 
      printf("Setup failed\n"); 
      return (-1); 
   }
   else 
   { 
      printf("Unexpected response: %s\n", str); 
      return (-2); 
   }
   return(st);
}

int r_cs(bglv *bgp, char *str)
{
   int st;

   str[0] = '\0'; 
 
/*
 *  First read the 44 characters that have always been there
 */
#ifdef ON_MAC
   st = read_mac_sp(bgp->str_len, &str[0]);
#endif
#ifdef ON_SGI
   st = read(bgp->sp_fd,str,bgp->str_len);
#else
   st = r_pc(bgp->sp_fd, str);
#endif
   if (st < 0)
   {
      perror("r_cs() ");
      return(-1);
   }
   if (str[0] == 'C' && str[bgp->str_len - 1] == '\n')
      return(st);
   else
      return(-1);
}

void check_4_encoders(bglv *bgp)
{
   int st;
   char str[44];

   str[0] = '\0'; 
 
   st = w_lv(bgp->sp_fd, "t");
/*
 *  Now see if there are encoders
 */
#ifdef ON_MAC
   st = read_mac_sp(bgp->str_len, &str[0]);
#endif
#ifdef ON_SGI
  sleep(1);
  st = read(bgp->sp_fd,str,44);
#else
   Sleep(500);
   st = r_pc(bgp->sp_fd, str);
#endif
   if (st < 0)
   {
      perror("check_4_encoders() ");
      return;
   }
   if ( str[1] == 'e' )
   {
      if (str[2] == '4' )
         bgp->box_type = ENC4;
      else if (str[2] == '8' )
         bgp->box_type = ENC8;
      printf("LV has %c encoders\n", str[2]);
   }
}
